﻿using Newtonsoft.Json;
using StoreHelper;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Data.Xml.Dom;
using Windows.Storage;
using Windows.System;
using Windows.UI.Notifications;

namespace CorpStoreTasks
{
    public sealed class CheckForNewApps : IBackgroundTask
    {
        //Log _log = new Log();
        TileUpdater updater = TileUpdateManager.CreateTileUpdaterForApplication();

        async public void Run(IBackgroundTaskInstance taskInstance)
        {
            // handle cancel request in the event our background task gets canceled
            taskInstance.Canceled += (IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) =>
            {
                // TODO: Execute code to cleanup task if it is canceled before running to completion...
                // NOTE: If this code takes more than 5 seconds to execute, the process is killed
            };

            // must get deferral object so that we can call async calls inside!
            var deferralObj = taskInstance.GetDeferral();

            // attempt to get latest package list using launch to desktop app
            await updateLiveTileAsync();

            await showToastsAsync();

            deferralObj.Complete();
        }


        private async Task<bool> showToastsAsync()
        {
            bool blnOK = false;

            try
            {
                // allocate folder to where all our 5 most recent tiles are stored
                StorageFolder folder = await ApplicationData.Current.LocalFolder.GetFolderAsync("Toasts");

                // now iterate through all xml files in that folder, creating a toast for each
                var files = (await folder.GetFilesAsync()).Where(f => System.IO.Path.GetExtension(f.Name).Equals(".xml", StringComparison.OrdinalIgnoreCase));
                foreach (var file in files)
                {
                    string rawData = await FileIO.ReadTextAsync(file);
                    XmlDocument xml = new XmlDocument(); xml.LoadXml(rawData);

                    var notif = new ToastNotification(xml);
                    ToastNotificationManager.CreateToastNotifier().Show(notif);

                    // delete toast xml file so we don't toast again!
                    await file.DeleteAsync();
                }
                blnOK = true;
            }
            catch (Exception ex)
            {
                logErr("Unhandled exception while trying to show toasts for most recent Corp apps: {0}", ex.Message);
                blnOK = false;
            }

            return blnOK;
        }


        /// <summary>
        /// This method attempts to update the primary app tile with the data contained in 
        /// local\Toasts\lastFeatured.json which has been written to by CorpStoreServer.exe.  A 
        /// list of images and appNames which will derived from the json read.  This info
        /// will be then used as xml content to update our primary tile.
        /// </summary>
        private async Task<bool> updateLiveTileAsync()
        {
            bool blnOK = false;
            List<string> images = new List<string>();
            List<string> appNames = new List<string>();
            List<PackageInfo> featuredList;

            try
            {
                // clear all app tiles first
                clearAppTiles();

                // load master catalog so that we can get the featured list
                StorageFile catalogFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appdata:///local/Toasts/LastFeatured.json"));
                string rawData = await FileIO.ReadTextAsync(catalogFile);
                featuredList = JsonConvert.DeserializeObject<List<PackageInfo>>(rawData);

                // now iterate through all files in that folder, creating a tile image for each
                foreach (PackageInfo app in featuredList)
                {
                    // assume corpStoreServer wrote the logo image with a filename of <pkg-name>_logo.png
                    images.Add(string.Format(@"ms-appdata:///Local/AppFiles/{0}_logo.png", app.Name));
                    appNames.Add(app.DisplayName);
                }

                defineTile(images, appNames);
            }
            catch (Exception ex)
            {
                logErr("Unhandled exception in updateAppTile: " + ex.Message);
            }

            return blnOK;
        }

        private void defineTile(List<string> images, List<string> appNames)
        {
            XmlDocument xml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150PeekImageCollection01);

            setXmlElements(xml, images, appNames);
            TileNotification notification = new TileNotification(xml);
            updater.Update(notification);
            logInfo("Sent update for tile with app names {0}", string.Join(",", appNames));
        }


        /// <summary>
        /// 
        /// <tile>
        ///  <visual version="2">
        ///    <binding template="TileWide310x150PeekImageCollection01" fallback="TileWidePeekImageCollection01">
        ///      <image id="1" src="image1.png" alt="larger image"/>
        ///      <image id="2" src="image2.png" alt="small image, row 1, column 1"/>
        ///      <image id="3" src="image3.png" alt="small image, row 1, column 2"/>
        ///      <image id="4" src="image4.png" alt="small image, row 2, column 1"/>
        ///      <image id="5" src="image5.png" alt="small image, row 2, column 2"/>
        ///      <text id="1">Text Field 1 (larger text)</text>
        ///      <text id="2">Text Field 2</text>
        ///    </binding>  
        ///  </visual>
        ///</tile>
        ///
        /// </summary>
        /// <param name="xml"></param>
        /// <param name="images"></param>
        /// <param name="appNames"></param>
        private void setXmlElements(XmlDocument xml, List<string> images, List<string> appNames)
        {
            var imageNodes = xml.GetElementsByTagName("image");
            var textNodes = xml.GetElementsByTagName("text");

            // set src attributes of all image elements - set first image = Corp Store logo always
            ((XmlElement)imageNodes[0]).SetAttribute("src", "ms-appx:///Assets/CorpStore 150x150.png");

            // define other 4 images = images of most recent apps installed
            for (int i = 0; i < 4; i++)
            {
                ((XmlElement)imageNodes[i+1]).SetAttribute("src", images[i]);
            }
                
            // now set text values
            if (textNodes.Count >= 2)
            {
                textNodes[0].InnerText = "Most Recent Apps";
                textNodes[1].InnerText = String.Join(", ", appNames);
            }
        }

        private void clearAppTiles()
        {
            TileUpdater updater = TileUpdateManager.CreateTileUpdaterForApplication();
            updater.Clear();
        }


        private void logInfo(string format, params object[] p)
        {
            Debug.WriteLine("INFO: " + string.Format(format, p));
        }

        private void logErr(string format, params object[] p)
        {
            Debug.WriteLine("ERR!: " + string.Format(format, p));
        }
    }
}
